#ifndef MASTER_H
#define MASTER_H
#include <string>
#include <map>
#include <ctime>
#include <pthread.h>
#include "dss_common.h"
#include "MiRpc.h"

using namespace std;

class Master;

/** master state **/
enum {
	PREPARE = 0,
	ACTIVE,
	EXIT,
};

enum {
	DOWN = 0,
	UP,
};


struct ChunkServer {
	uint64_t id;
	string uri;
	int session_id;

	//TODO need lock ??
	uint32_t state; //0: DOWN, 1: UP
	uint32_t cluster_total; //the number of total clusters in blobstore
	uint32_t cluster_free;  //the number of free clusters in blobstore
	uint32_t cluster_size;  //the size of a cluster, usually 1MB
	uint32_t io_unit_size;  //read or write minimum size, usually 4KB, need or not??
};

struct ChunkOp {
	Master *master;
	struct RpcExecution *rpc_ex;
	struct dss_msg *dss_request;
	struct dss_msg *dss_response;
	uint64_t total_response;
	uint64_t cur_response;
};

struct HeartbeatInfo {
	uint64_t chunkserver;
	//TODO need lock??
	uint64_t last_tid;
	clock_t last_heartbeat;
};

class Master {
public:
	uint64_t id;
	string conf;
	string uri;
	uint32_t heartbeat_interval;
	uint32_t state;
	pthread_t heartbeat_th;
	uint64_t last_active;
	map<uint64_t, struct ChunkServer> chunkservers;
	map<uint64_t, struct HeartbeatInfo> heartbeatmap;

	RdmaRpc *rpc_client;
	RdmaRpc *rpc_server;
	void *mem;
	MemoryManager *mm;

	uint64_t cur_id;
	uint64_t cur_cs;

public:
	Master(uint64_t id_, string conf_) :
		id(id_),
		conf(conf_),
		heartbeat_interval(HEARTBEAT_INTERVAL),
		state(PREPARE),
		last_active(0),
		rpc_client(NULL),
		rpc_server(NULL),
		mem(NULL),
		mm(NULL),
		cur_id(0),
		cur_cs(0)
	{}

	~Master(){}
	int parse_conf();
	static void chunk_op_service(void *self, void *ex, void *master);
	static void sys_status_service(void *self, void *ex, void *master);
	static void heartbeat_service(void *self, void *ex, void *master);

	void handle_op_create(struct ChunkOp *op);
	void handle_op_list(struct ChunkOp *op);
	static void create_cb(void *arg1, void *arg2, void *ctx);
	static void list_cb(void *arg1, void *arg2, void *ctx);
	static void *heartbeat_main(void *arg);
	void heartbeat_manager();
	int chunkserver_select();
	void prepare();
	void exit();

};
#endif
